﻿using System.Reflection;

namespace Devonline.AspNetCore;

/// <summary>
/// 排序选项
/// 排序方式只判断是否 desc 字样
/// </summary>
public class OrderbyOption
{
    /// <summary>
    /// 逆向排序比较字符串
    /// </summary>
    private const string ORDERBY_DESC = "desc";
    /// <summary>
    /// 当前排序对象的排序值字符串表示形式
    /// </summary>
    private readonly string? _orderby;
    /// <summary>
    /// 当前表达式的类型主体
    /// </summary>
    private readonly Type? _type;

    /// <summary>
    /// 默认构造函数
    /// </summary>
    public OrderbyOption()
    {
    }
    /// <summary>
    /// 从排序字符串递归获取排序方式
    /// 原始输入字符串样式如下:
    /// Id, Name asc, Age desc
    /// </summary>
    /// <param name="orderby"></param>
    public OrderbyOption(Type type, string orderby)
    {
        _type = type;
        var index = orderby.IndexOf(AppSettings.CHAR_COMMA);
        if (index > 0)
        {
            _orderby = orderby[0..(index - 1)];
            Then = new OrderbyOption(type, orderby[index..]);
        }
        else
        {
            _orderby = orderby;
        }

        if (index != 0)
        {
            //_orderby is not AppSettings.CHAR_COMMA, then
            var orderbys = _orderby.Split(AppSettings.CHAR_SPACE, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
            if (orderbys.Length > 0)
            {
                Field = orderbys[0];
                if (_type.GetMember(Field).IsNullOrEmpty())
                {
                    throw new ArgumentException($"the property or field {Field} of type {_type.Name} not found!");
                }
            }

            Asc = true;
            if (orderbys.Length > 1)
            {
                Asc = orderbys[1].ToUpperInvariant() != ORDERBY_DESC.ToUpperInvariant();
            }
        }
    }

    /// <summary>
    /// 当前排序字段
    /// </summary>
    public string? Field { get; set; }
    /// <summary>
    /// 是否顺序
    /// </summary>
    public bool Asc { get; set; }
    /// <summary>
    /// 下一个排序字段
    /// </summary>
    public OrderbyOption? Then { get; set; }

    /// <summary>
    /// 重写的 ToString 方法来输出字符形式的 orderby 表达式
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        var result = Field;
        if (!Asc)
        {
            result += AppSettings.CHAR_SPACE + ORDERBY_DESC;
        }

        if (Then != null)
        {
            result += AppSettings.CHAR_COMMA + AppSettings.CHAR_SPACE + Then.ToString();
        }

        return result ?? string.Empty;
    }
}

/// <summary>
/// 排序选项
/// 排序方式只判断是否 desc 字样
/// </summary>
public class OrderbyOption<T>
{
    /// <summary>
    /// 逆向排序比较字符串
    /// </summary>
    private const string ORDERBY_DESC = "desc";
    /// <summary>
    /// 当前排序对象的排序值字符串表示形式
    /// </summary>
    private readonly string? _orderby;
    /// <summary>
    /// 当前表达式的类型主体
    /// </summary>
    private readonly Type? _type = typeof(T);

    /// <summary>
    /// 默认构造函数
    /// </summary>
    public OrderbyOption()
    {
    }
    /// <summary>
    /// 从排序字符串递归获取排序方式
    /// 原始输入字符串样式如下:
    /// Id, Name asc, Age desc
    /// </summary>
    /// <param name="orderby"></param>
    public OrderbyOption(string orderby)
    {
        var index = orderby.IndexOf(AppSettings.CHAR_COMMA);
        if (index > 0)
        {
            _orderby = orderby[0..(index - 1)];
            Then = new OrderbyOption<T>(orderby[index..]);
        }
        else
        {
            _orderby = orderby;
        }

        if (index != 0)
        {
            //_orderby is not AppSettings.CHAR_COMMA, then
            var orderbys = _orderby.Split(AppSettings.CHAR_SPACE, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
            if (orderbys.Length > 0)
            {
                Field = orderbys[0];
                if (_type.GetMember(Field, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).IsNullOrEmpty())
                {
                    throw new ArgumentException($"the property or field {Field} of type {_type.Name} not found!");
                }
            }

            Asc = true;
            if (orderbys.Length > 1)
            {
                Asc = orderbys[1].ToUpperInvariant() != ORDERBY_DESC.ToUpperInvariant();
            }
        }
    }

    /// <summary>
    /// 当前排序字段
    /// </summary>
    public string? Field { get; set; }
    /// <summary>
    /// 是否顺序
    /// </summary>
    public bool Asc { get; set; }
    /// <summary>
    /// 下一个排序字段
    /// </summary>
    public OrderbyOption<T>? Then { get; set; }

    /// <summary>
    /// 重写的 ToString 方法来输出字符形式的 orderby 表达式
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        var result = Field;
        if (!Asc)
        {
            result += AppSettings.CHAR_SPACE + ORDERBY_DESC;
        }

        if (Then != null)
        {
            result += AppSettings.CHAR_COMMA + AppSettings.CHAR_SPACE + Then.ToString();
        }

        return result ?? string.Empty;
    }
}